package com.lzp.java.jdk8.lambda.c5;

import com.lzp.java.jdk8.lambda.pojo.Album;
import com.lzp.java.jdk8.lambda.pojo.Artist;
import com.lzp.java.jdk8.lambda.pojo.SampleData;
import org.antlr.v4.runtime.tree.Tree;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.*;
import static org.springframework.test.util.AssertionErrors.*;

/**
 * @description: 方法引用、收集器
 * @author: lzp
 * @createTime: 2021-07-18 17:03
 **/
public class MethodReferenceAndCollect {
    public static void main(String[] args) {
        // 方法引用，用来重用已有方法
        BiFunction<String, String, Artist> function = (x, y) -> new Artist(x, y);
        BiFunction<String, String, Artist> function1 = Artist::new;
        Function<Artist, String> getName = Artist::getName;

        // 元素顺序
        // 有序list
        List<Integer> numbers = asList(4, 2, 3, 1);
        List<Integer> list = numbers.stream().collect(toList());

        // 无序set，生成的set有序的？
        Set<Integer> set = new HashSet<>(numbers);
        List<Integer> setList = set.stream().collect(toList());
        List<Integer> sortedList = set.stream().sorted().collect(toList());
        List<Integer> unorderedList = set.stream().unordered().collect(toList());
        System.out.println(set);

        // Collectors收集器
        TreeSet<Integer> treeSet = set.stream().collect(Collectors.toCollection(TreeSet::new));
        Set<Integer> set1 = set.stream().collect(Collectors.toSet());
        Optional<Artist> artist = biggestGroup(SampleData.threeArtists());

        // partioningBy收集器 -- 数据分块
        Map<Boolean, List<Artist>> booleanListMap = bandsAndSolo(SampleData.threeArtists());

        // 数据分组 -- groupingBy
        Map<Artist, List<Album>> artistListMap = albumsByArtist(SampleData.albums);

        // 组合收集器
        Map<Artist, Long> artistLongMap = numberByAlbums(SampleData.albums);
        Map<Artist, List<String>> artistListMap1 = nameOfAlbums(SampleData.albums);

        // 使用流和收集器拼接名字
        String joinName = SampleData.threeArtists()
                .map(Artist::getName)
                .collect(Collectors.joining(", ", "[", "]"));
        System.out.println(joinName);
    }

    /**
     * 收集每个艺术家的专辑名 -- 使用mapping下游收集器
     *
     * @param albums
     * @return
     */
    public static Map<Artist, List<String>> nameOfAlbums(Stream<Album> albums) {
        return albums.collect(groupingBy(Album::getMainMusician, mapping(Album::getName, toList())));
    }

    /**
     * 统计每个艺术家的专辑数 -- 使用counting下游收集器
     *
     * @param albums
     * @return
     */
    public static Map<Artist, Long> numberByAlbums(Stream<Album> albums) {
        return albums.collect(groupingBy(Album::getMainMusician, counting()));
    }

    /**
     * 根据主唱区分专辑
     *
     * @param albums
     * @return
     */
    public static Map<Artist, List<Album>> albumsByArtist(Stream<Album> albums) {
        return albums.collect(groupingBy(Album::getMainMusician));
    }

    /**
     * 区分乐队和solo
     *
     * @param artists
     * @return
     */
    public static Map<Boolean, List<Artist>> bandsAndSolo(Stream<Artist> artists) {
        // return artists.collect(partitioningBy(artist -> artist.isSolo()));
        return artists.collect(partitioningBy(Artist::isSolo));
    }

    /**
     * 找出成员最多的乐队--collect返回值
     *
     * @param artists
     * @return
     */
    public static Optional<Artist> biggestGroup(Stream<Artist> artists) {
        Function<Artist, Long> getCount = artist -> artist.getMembers().count();
        return artists.collect(maxBy(Comparator.comparing(getCount)));
    }

    /**
     * collect返回数值
     *
     * @param albums
     * @return
     */
    public static double averageNumberOfTracks(List<Album> albums) {
        return albums.stream()
                .collect(averagingInt(album -> album.getTrackList().size()));
    }
}
